package com.keyue.common.utils;


import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

/**
 * @Auther: dengbin
 * @Date: 2020/9/1
 * 基于Java8的时间工具类
 */
public class DateUtils {
    /**
     * 例如:2018-12-28
     */
    public static final String DATE = "yyyy-MM-dd";
    /**
     * 例如:2018.12.28
     */
    public static final String DATE_WITH_POINT = "yyyy.MM.dd";
    /**
     * 例如:2018-12-28 10:00:00
     */
    public static final String DATE_TIME = "yyyy-MM-dd HH:mm:ss";
    /**
     * 例如:2018-12-28 10:00:00:215
     */
    public static final String DATE_TIME_MS = "yyyy-MM-dd HH:mm:ss.SSS";
    /**
     * 例如:10:00:00
     */
    public static final String TIME = "HHmmss";
    /**
     * 例如:10:00:00
     */
    public static final String TIME_HAVE_SECOND = "HH:mm:ss";
    /**
     * 例如:10:00
     */
    public static final String TIME_WITHOUT_SECOND = "HH:mm";

    /**
     * 例如:2018-12-28 10:00
     */
    public static final String DATE_TIME_WITHOUT_SECONDS = "yyyy-MM-dd HH:mm";

    /**
     * 例如 2020/04/16 12:23:0
     */
    public static final String DATE_TIME_WITHOUT_SECONDS_OTHER = "yyyy/MM/dd HH:mm:ss";

    /**
     * 例如：2020年04月23日 10:00
     */
    public static final String DATE_CHINESE_TIME = "yyyy年MM月dd日 HH:mm";

    /**
     * 例如：20181228100000215
     */
    public static final String MAX_DATE = "9999-12-31 59:59:59";

    /**
     * 例如：20210822082134
     */
    public static final String DATE_TIME_HMS = "yyyyMMddHHmmssSSS";

    public static final String YYMMDD = "yyyyMMdd";

    public static final String YMMDD = "yyMMdd";

    public static final String YYMMDDHHMMSS = "yyMMddHHmmss";

    public static final String MONTH_TIME = "MM-dd HH:mm:ss";

    public static LocalDateTime getCurrentTime() {
        LocalDateTime now = LocalDateTime.now();
        return now;
    }

    public static Date getNextDay() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime tomorrow = now.minusDays(-1);
        return Date.from(tomorrow.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static Date getAppointDay(Integer count) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime tomorrow = now.minusDays(count);
        return Date.from(tomorrow.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取年
     *
     * @return 年
     */
    public static int getYear() {
        LocalDateTime localDateTime = LocalDateTime.now();
        return localDateTime.get(ChronoField.YEAR);
    }

    /**
     * 获取月份
     *
     * @return 月份
     */
    public static int getMonth() {
        LocalDateTime localDateTime = LocalDateTime.now();
        return localDateTime.get(ChronoField.MONTH_OF_YEAR);
    }

    /**
     * 获取某月的第几天
     *
     * @return 几号
     */
    public static int getMonthOfDay() {
        LocalDateTime localDateTime = LocalDateTime.now();
        return localDateTime.get(ChronoField.DAY_OF_MONTH);
    }

    /**
     * 格式化日期为字符串
     *
     * @param date    date
     * @param pattern 格式
     * @return 日期字符串
     */
    public static String formatOrElseBlank(Date date, String pattern) {
        if (date == null || pattern == null) {
            return "";
        }
        Instant instant = date.toInstant();

        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());

        return localDateTime.format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 格式化日期为字符串
     *
     * @param date    date
     * @param pattern 格式
     * @return 日期字符串
     */
    public static String format(Date date, String pattern) {

        Instant instant = date.toInstant();

        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());

        return localDateTime.format(DateTimeFormatter.ofPattern(pattern));
    }

    public static String formatNow(String pattern) {
        LocalDateTime localDateTime = LocalDateTime.now();

        return localDateTime.format(DateTimeFormatter.ofPattern(pattern));
    }


    public static String format(LocalDateTime date, String pattern) {
        return date.format(DateTimeFormatter.ofPattern(pattern));
    }

    public static String format(LocalDate date, String pattern) {
        return date.format(DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 解析字符串日期为LocalDateTime
     *
     * @param dateStr 日期字符串
     * @param pattern 格式
     * @return Date
     */
    public static LocalDateTime parse(String dateStr, String pattern) {
        return LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 解析字符串日期为LocalDateTime
     *
     * @param dateStr 日期字符串
     * @param pattern 格式
     * @return Date
     */
    public static LocalDateTime parseStrByPattern(String dateStr, String pattern) {
        try {
            return parse(dateStr, pattern);
        } catch (Exception e) {
            return getCurrentTime();
        }
    }

    /**
     * 解析字符串日期为LocalDate
     *
     * @param dateStr
     * @param pattern
     * @return
     */
    public static LocalDate parseDate(String dateStr, String pattern) {
        return LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * @param dateTimeStr
     * @param prePattern
     * @param expectPattern
     * @return
     */
    public static String format(String dateTimeStr, String prePattern, String expectPattern) {
        LocalDateTime localDateTime = parseDate(dateTimeStr, prePattern).atStartOfDay();
        return localDateTime.format(DateTimeFormatter.ofPattern(expectPattern));
    }

    /**
     * String -> Date
     *
     * @param date
     * @return
     */
    public static Date parseStringToDate(String date, String pattern) {
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        try {
            return sdf.parse(date);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 为Date增加分钟,减传负数
     *
     * @param date        日期
     * @param plusMinutes 要增加的分钟数
     * @return 新的日期
     */
    public static Date addMinutes(Date date, Long plusMinutes) {
        LocalDateTime dateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        LocalDateTime newDateTime = dateTime.plusMinutes(plusMinutes);
        return Date.from(newDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 增加时间
     *
     * @param date date
     * @param hour 要增加的小时数
     * @return new date
     */
    public static Date addHour(Date date, Long hour) {
        LocalDateTime dateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        LocalDateTime localDateTime = dateTime.plusHours(hour);
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * @return 返回当天的起始时间
     */
    public static Date getStartTime() {

        LocalDateTime now = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
        return localDateTime2Date(now);
    }


    /**
     * @return 返回当天的结束时间
     */
    public static Date getEndTime() {
        LocalDateTime now = LocalDateTime.now().withHour(23).withMinute(59).withSecond(59).withNano(999999999);
        return localDateTime2Date(now);
    }

    /**
     * @return 获取入参当天结束时间
     */
    public static LocalDateTime getEndTime(LocalDate localDate) {
        return localDate.atTime(23, 59, 59, 999999999);
    }

    /**
     * 减月份
     *
     * @param monthsToSubtract 月份
     * @return Date
     */
    public static Date minusMonths(long monthsToSubtract) {
        LocalDate localDate = LocalDate.now().minusMonths(monthsToSubtract);

        return localDate2Date(localDate);
    }

    /**
     * LocalDate类型转为Date
     *
     * @param localDate LocalDate object
     * @return Date object
     */
    public static Date localDate2Date(LocalDate localDate) {

        ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());

        return Date.from(zonedDateTime.toInstant());
    }

    /**
     * Date类型转为LocalDateTime
     *
     * @param date Date object
     * @return localDate LocalDateTime
     */
    public static LocalDateTime date2LocalDateTime(Date date) {

        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        return localDateTime;
    }


    /**
     * LocalDateTime类型转为Date
     *
     * @param localDateTime LocalDateTime object
     * @return Date object
     */
    public static Date localDateTime2Date(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 查询当前年的第一天
     *
     * @param pattern 格式，默认格式yyyyMMdd
     * @return 20190101
     */
    public static String getFirstDayOfCurrentYear(String pattern) {
        LocalDateTime localDateTime = LocalDateTime.now().withMonth(1).withDayOfMonth(1);

        if (StringUtils.isEmpty(pattern)) {
            pattern = "yyyyMMdd";
        }

        return format(localDateTime2Date(localDateTime), pattern);
    }

    /**
     * 查询前一年最后一个月第一天
     *
     * @param pattern 格式，默认格式yyyyMMdd
     * @return 20190101
     */
    public static String getLastMonthFirstDayOfPreviousYear(String pattern) {
        LocalDateTime localDateTime = LocalDateTime.now().minusYears(1L).withMonth(12).withDayOfMonth(1);

        if (StringUtils.isEmpty(pattern)) {
            pattern = "yyyyMMdd";
        }

        return format(localDateTime2Date(localDateTime), pattern);
    }

    /**
     * 查询前一年最后一个月第一天
     *
     * @param pattern 格式，默认格式yyyyMMdd
     * @return 20190101
     */
    public static String getLastMonthLastDayOfPreviousYear(String pattern) {
        LocalDateTime localDateTime = LocalDateTime.now().minusYears(1L).with(TemporalAdjusters.lastDayOfYear());

        if (StringUtils.isEmpty(pattern)) {
            pattern = "yyyyMMdd";
        }

        return format(localDateTime2Date(localDateTime), pattern);
    }

    /**
     * 获取当前日期
     *
     * @param pattern 格式，默认格式yyyyMMdd
     * @return 20190101
     */
    public static String getCurrentDay(String pattern) {
        LocalDateTime localDateTime = LocalDateTime.now();

        if (StringUtils.isEmpty(pattern)) {
            pattern = "yyyyMMdd";
        }

        return format(localDateTime2Date(localDateTime), pattern);
    }

    public static String getTransitionTime(LocalDateTime time, String pattern) {
        if (StringUtils.isEmpty(pattern)) {
            pattern = "yyyyMMdd";
        }
        return format(localDateTime2Date(time), pattern);
    }


    /**
     * 用于判断两个时间段有没有重合， 重合: true，未重合: false
     *
     * @param aStartTime
     * @param aEndTime
     * @param bStartTime
     * @param bEndTime
     * @return
     * @author A80068
     */
    public static boolean judgeTimeSlotCoincidence(LocalDateTime aStartTime, LocalDateTime aEndTime, LocalDateTime bStartTime, LocalDateTime bEndTime) {
        /**
         * 旧版
         */
        //boolean flag;
        //if(aStartTime.isAfter(bStartTime)){
        //    if (aStartTime.isBefore(bEndTime) || aStartTime.isEqual(bEndTime)){
        //        flag = true;
        //    }else{
        //        flag = false;
        //    }
        //}else if(aStartTime.isBefore(bStartTime)){
        //    if(aEndTime.isAfter(bStartTime) || aEndTime.isEqual(bStartTime)){
        //        flag = true;
        //    }else{
        //        flag = false;
        //    }
        //}else{
        //    flag = true;
        //}
        //return flag;
        /**
         * 优化版
         */
        boolean flag = false;
        if ((aStartTime.isBefore(bEndTime) || aStartTime.isEqual(bEndTime))) {
            if ((aEndTime.isAfter(bStartTime)) || aEndTime.isEqual(bStartTime)) {
                flag = true;
            }
        }
        return flag;
    }

    /**
     * @param aStartTimeStr
     * @param aEndTimeStr
     * @param bStartTimeStr
     * @param bEndTimeStr
     * @return
     * @author A80068
     */
    public static boolean judgeTimeSlotCoincidenceString(String aStartTimeStr, String aEndTimeStr, String bStartTimeStr, String bEndTimeStr) {

        LocalDateTime aStartTime = parse(aStartTimeStr, DATE_TIME);
        LocalDateTime aEndTime = parse(aEndTimeStr, DATE_TIME);
        LocalDateTime bStartTime = parse(bStartTimeStr, DATE_TIME);
        LocalDateTime bEndTime = parse(bEndTimeStr, DATE_TIME);

        return judgeTimeSlotCoincidence(aStartTime, aEndTime, bStartTime, bEndTime);
    }

    /**
     * @param strGMT
     * @return
     * @throws ParseException
     * @throws ParseException
     */
    public static Date getCST(String strGMT) throws ParseException, ParseException {
        DateFormat df = new SimpleDateFormat("EEE, d-MMM-yyyy HH:mm:ss z", Locale.ENGLISH);
        return df.parse(strGMT);
    }

    /**
     * @param dateCST
     * @return
     */
    public static Date getGMT(Date dateCST) throws ParseException {
        DateFormat df = new SimpleDateFormat("EEE, d-MMM-yyyy HH:mm:ss z", Locale.ENGLISH);
        df.setTimeZone(TimeZone.getTimeZone("GMT")); // modify Time Zone.
        return df.parse(df.format(dateCST));
    }

    /**
     * LocalDateTime转化为cron表达式
     *
     * @param dateTime
     * @return
     */
    public static String dateToCron(LocalDateTime dateTime) {
        if (dateTime == null) {
            return "";
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ss mm HH dd MM ? yyyy");
        return formatter.format(dateTime);
    }

    /**
     * cron表达式转为LocalDateTime
     *
     * @param cron
     * @return
     */
    public static LocalDateTime cronToDate(String cron) {
        if (StringUtils.isNotBlank(cron)) {
            return null;
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ss mm HH dd MM ? yyyy");
        return LocalDateTime.parse(cron, formatter);
    }

    public static String timeToString(long time) {
        DateTimeFormatter ftf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        return ftf.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault()));
    }

    public static String timeToString(String time) {
        try {
            return timeToString(Long.parseLong(time));
        } catch (Exception e) {
        }
        return time;
    }

    /**
     * 比较时间大小
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int compareDate(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            return -2;
        }
        if (date1.getTime() < date2.getTime()) {
            return -1;
        } else if (date1.getTime() > date2.getTime()) {
            return 1;
        }
        return 0;
    }

    /**
     * 判斷两个时间是否在同一分钟
     */
    public static boolean isMinuteIdentical(LocalDateTime date1, LocalDateTime date2) {
        return date1.getYear() == date2.getYear() && date1.getMonth() == date2.getMonth() && date1.getMinute() == date2.getMinute();
    }

    /**
     * 时区
     */
    public static class Zone {
        public static final String GMT8 = "GMT+8";
    }
}
